/*!
 * This file is part of jQuery Select List (drop-down list) Plugin.
 * 
 * jQuery Select List (drop-down list) Plugin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * jQuery Select List (drop-down list) Plugin is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with jQuery Select List (drop-down list) Plugin.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * ----------------------------------------------------------------------------------------------------
 * 
 * jQuery Select List (drop-down list) Plugin
 * 
 * Versión 2.2
 * 
 * author: Joan Sebastián Muñoz Ramírez
 * Website (http://www.joanmunoz.com/)
 * 24 Jun 2011
 * 
 * Historial:
 * 
 * 	1.0 - Released. (26 October 2010)
 * 	2.0 - Poder asignarle clases CSS a los elementos del select list.  (27 Abril 2011)
 * 	2.1 - Poder hacer Rollover. (28 Abril 2011)
 *  2.2 - Poder reiniciar. (24 Junio 2011)
 *  2.3 - Al reiniciar respetar las opciones que ya se le habían asignado (1 Julio 2011)
 *  2.4 - Poder destruir el plugin (1 Julio 2011)
 * 
 * Por hacer:
 * 
 * 	- Especificar que puede estar desabilitado (disabled)
 * 	- Especificar que multiples opciones pueden ser seleccionadas (multiple)
 * 	- Especificar el número de opciones visibles en la lista (size)
 *  - Encotrar los elementos al escribir sobre el texto
 *  - Poder utilizar sprites
 *  - Heredar el estilo del <select> al cual se le aplicará el plugin
 *  - Poder aplicar animaciones en la lista
 *  - Poder abrir la lista y cerrarla
 * 
 */
(function($){
	
	/**
	 * Aquí van todos los métodos que se necesitan
	 */
	var Methods = {
			
			/**
			 * Crea el plugin del <select>.
			 * :) Me pareció divertido llamar a esta función "bornAgain" (Nace de nuevo).
			 * Me inspiré en el intérprete de comandos "bash" (born-again Shell)
			 * 
			 * @param object UserOptions - Contiene las opciones del usuario
			 */
			bornAgain : function( UserOptions ) {
				
				/*
				 * Las opciones por default del plugin
				 */
				var DefaultOptions = {
						prefix : '', // Prefijo que ayuda a que no se duplique el select list
						image_background : 'images/selectList.png', // La imagen que se mostrará como select list
						image_height : '27px', // La altura de la imagen
						image_width : '198px', // El ancho de la imagen
						select_class : '', // El nombre de la clase que se le asiganará al select
						text_class : 'selectListText', // El nombre de la clase que se le asignará al texto
						list_class : 'selectListOptions', // El nombre de la clase para el contenedor de las opciones
						ul_class : 'selectList_ul', // El nombre de la clase para la UL que contiene las opciones
						option_class : 'selectList_option', // El nombre de la clase para cada opción
						rollover : true, // true = La imagen tiene rollover usando sprite
						list_height : 'auto', // La altura máxima de la lista. auto es por default
						callback : null // Función que es invocada cuando se da click sobre algún elemento
					};
				
				// Combina las opciones por default con las enviadas por el usuario
				var FinalOptions = $.extend( DefaultOptions, UserOptions);
				
				/*
				 * Pasa por cada uno de los <select> a los cuales
				 * se aplicará el plugin
				 */
				this.each(function( index ) {
					
					var select = $(this); // Crea una instancia del <select>
					
					/*
					 * Guarda las opciones finales para utilizarlo a la hora de reiniciar
					 */
					select.data('FinalOptions', FinalOptions);
					
					/*
					 * Crea un <div> después del <select>
					 * Este <div> Es el contenedor del plugin
					 */
					select.after('<div class="selectListContainer_' + FinalOptions.prefix + index + ' selectListContainer"></div>');
							
					var parent_element = select.parent().find('.selectListContainer_' + FinalOptions.prefix + index ); // Asigna el contenedor a una variable
					var plugin_class = 'selectList_' + FinalOptions.prefix + index; // Nombre de la clase para el plugin
					
					/*
					 * Agrega un <div> dentro del contenedor.
					 * El <div> contendrá todos los elementos
					 */
					parent_element.append('<div class="' + plugin_class + '"></div>');
					var div = parent_element.find('.' + plugin_class);
					
					
					/*
					 * Nombre de las clases de los elementos del plugin
					 */
					var text_class = 'selectListText_' + FinalOptions.prefix + index; // Nombre de la clase para el texto
					var anchor_class = 'selectListBtn_' + FinalOptions.prefix + index; // Nombre de la clase para el anchor
					var list_class = 'selectListOptions_' + FinalOptions.prefix + index; // Nombre de la clase para el contenedor de la opciones
					
					
					/*
					 * Agrega estilos al <div> del plugin y crea dentro los elementos
					 */
					div
					.css({
						'background-image' : 'url(' + FinalOptions.image_background + ')',
						'height' : FinalOptions.image_height,
						'width' : FinalOptions.image_width
					})
					.addClass( FinalOptions.select_class )
					.append('<div class="' + text_class + '"></div>')
					.append('<a href="javascript:void(0);" class="' + anchor_class + '"></a>')
					.append('<div class="' + list_class + '"></div>');
					
					// Si el usuario no modifica la propiedad position se le asignará relative por default
					if( div.css('position') == 'static' ) {
						div.css('position','relative');
					}
					
					
					/*
					 * Asigna estilo al <div> que contiene el texto
					 */
					var divText = div.find('.' + text_class);
					divText.addClass( FinalOptions.text_class );
					divText.css({
						'height' : FinalOptions.image_height,
						'overflow' : 'hidden'
					});
					
					/*
					 * Asigna estilo a la <a> que funciona como botón
					 */
					var btn = div.find('.' + anchor_class);
					btn.css({
						'display' : 'block',
						'height' : FinalOptions.image_height,
						'left' : 0,
						'outline' : 'none',
						'position' : 'absolute',
						'top' : 0,
						'width' : FinalOptions.image_width
					});
					
					
					/*
					 * Asigan estilo al <div> que contiene las opciones
					 */
					var listDiv = div.find('.' + list_class );
					listDiv.addClass( FinalOptions.list_class );
					listDiv.css({
						'display' : 'none',
						'position' : 'absolute',
						'left' : 0,
						'top' : FinalOptions.image_height
					});
					
					
					/*
					 * LLena las opciones
					 */
					var list = '<ul class="' + FinalOptions.ul_class + '">';
					select.children('option').each(function( index ) {
						if( index == 0 || $(this).attr('selected') ) {
							divText.html( $(this).text() );
						}
						
			        	list += '<li><a href="javascript:void(0);" name="' + $(this).val() + '" class="' + FinalOptions.option_class + '">' + $(this).text() + '</a></li>';
			        });
					list += '</ul>';
					listDiv.append(list);
					
					
					/*
					 * Aplica scroll a la vista
					 */
					var list_height = FinalOptions.list_height;
					if(list_height != 'auto' && listDiv.height() > list_height.substr(0, list_height.length-2) ) {
						listDiv.css({
							'height' : FinalOptions.list_height,
							'overflow' : 'auto'
						});
					}
					
					
					/*
					 * Asigna el evento click de la <a> o botón del select
					 */
					btn.bind('click', function(){
						listDiv.slideDown("fast", function(){
							
							$(document).bind('click.selectList', function(){
								listDiv.slideUp("fast");
								$(document).unbind('click.selectList');
							});
							
						});			
					});
					
					
					/*
					 * Asigan el evento mouseenter y mouseleave a la <a> o botón del select
					 */
					if( FinalOptions.rollover == true ) {
						btn.bind('mouseenter mouseleave', function(event){
							if(event.type == 'mouseenter') {
								div.css('background-position', '0 -' + FinalOptions.image_height );
							} else if(event.type == 'mouseleave') {
								div.css('background-position', '0 0');
							}
						});
					}
					
					
					/*
					 * Las acciones de la <a> de cada opción
					 */
					listDiv.find('a').bind('click', function(e){
						e.preventDefault();
						
						var value = $(this).attr('name');
						var text = $(this).text();
						
						divText.html( text );
						select.children('option[value="' + value + '"]')[0].selected = true;
						
						// Llama la función que el usuario asigno
						if(FinalOptions.callback != null)
							FinalOptions.callback(value, text);
						
					});
					
					
					/*
					 * Oculta el <select>
					 */
					select.css({
						'display' : 'none'
					});
				
				});
				// END this.each
					
			},
			// END Methods.bornAgain
			
			/**
			 * Reinicia el plugin del <select>
			 * 
			 * @param object UserOptions - Contiene las opciones del usuario
			 */
			restart : function() {
				
				// Destuye el plugin
				Methods.destroy.apply(this);
				
				// Inserta el plugin
				Methods.bornAgain.apply( this, $.makeArray( $(this).data('FinalOptions') ) );
				
			},
			// END Methods.restart
			
			/**
			 * Destruye el plugin
			 */
			destroy : function() {
				
				this.each(function( i ){
					/*
					 * Verifica si existe el plugin
					 */
					if( $(this).next().hasClass('selectListContainer') ) {
						$(this).next().remove(); // Quita el plugin
						
						// Aparece de nuevo el <select>
						$(this).css({
							'display' : 'block'
						});
					}
				});
				
			}
			// END Methods.destroy
			
	};
	// END Methods
	
	
	/**
	 * Inicializa el Select List
	 */
	$.fn.selectList = function( method ){
		
		if ( Methods[method] ) {
			Methods[ method ].apply( this, arguments ); // Manda llamar algún método
		} else if ( typeof method === 'object' || !method ) {
			Methods.bornAgain.apply( this, arguments ); // Manda crear el plugin
		} else {
			alert( 'El método ' +  method + ' no existe en jquery.selectList' );
		}  
		
	}; 
	// END $.fn.selectList
	
	
})(jQuery);